package gui;

import java.util.HashMap;
import java.util.Map;
import com.rits.cloning.Cloner;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.print.PageLayout;
import javafx.print.PageOrientation;
import javafx.print.Paper;
import javafx.print.Printer;
import javafx.print.PrinterJob;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import javafx.scene.transform.Scale;
import javafx.stage.Stage;

import logic.Sudoku;

public class PrintPreveiw {
	static GridPane sudokus;
	static BorderPane content = new BorderPane();
	static Cloner cloner = new Cloner();
	private static Stage page = new Stage(); 
	private static Map<String,Integer> difficultyValues = new HashMap<String,Integer>();
	
	private PrintPreveiw()
	{}
	
	/**
	 * displays a print preview of generated sudokus in another stage(frame) closes once user has printed
	 */
	static void preveiwPrint()
	{		
		difficultyValues.put("Easy", Sudoku.EASY);
		createSudokus(4);
		
		FlowPane buttons = new FlowPane();
		buttons.setAlignment(Pos.CENTER);
		
		//print button
		Button printBTN = new Button(" Print "); 
		printBTN.setOnAction(new EventHandler<ActionEvent>() {
			
			@Override
			public void handle(ActionEvent arg0) {
				print(sudokus,page);
			}
		});
		
		// difficulty selector
		ObservableList<String> optionsDifficulty = FXCollections.observableArrayList("Easy");
		final ComboBox<String> difficultyCB = new ComboBox<String>(optionsDifficulty);
		difficultyCB.setValue("Easy");
		
		// puzzle options
		ObservableList<String> optionsPuzzles = FXCollections.observableArrayList("1","2","3","4");
		final ComboBox<String> numberCB = new ComboBox<String>(optionsPuzzles);
		numberCB.setValue("4");
		
		// reset puzzles
		Button resetPuzzle = new Button("Reset Puzzle :");
		resetPuzzle.setOnAction(new EventHandler<ActionEvent>() {

			@Override
			public void handle(ActionEvent arg0) {
				resetPuzzle(difficultyValues.get(difficultyCB.getValue()), Integer.valueOf(numberCB.getValue())-1);
			}
		});
		
		buttons.getChildren().add(resetPuzzle);
		buttons.getChildren().add(numberCB);
		buttons.getChildren().add(difficultyCB);
		buttons.getChildren().add(printBTN);
		content.setBottom(buttons);
		
		Scene scene = new Scene(content);
		page.setTitle("Sudoku Solver Print");
		page.setScene(scene);
		page.show();
	}
	
	/**
	 * creates sudokus to print 
	 * @param number
	 */
	private static void createSudokus(int number)
	{
		sudokus = new GridPane();
		sudokus.setPadding(new Insets(10, 10, 10, 10));
		sudokus.setVgap(5);
		sudokus.setHgap(5);
		for(int i = 0; i < number; i++)
		{
			resetPuzzle(Sudoku.EASY, i);
		}
		
		content.setCenter(sudokus);
	}
	
	/**
	 * recreates the puzzle at puzzle number position at supplied difficulty 
	 * 
	 * @param difficulty difficulty of new puzzle created
	 * @param puzzleNumber puzzle to recreate
	 */
	private static void resetPuzzle(int difficulty,int puzzleNumber)
	{
		GridPane sudokuN;
		sudokuN = new GridPane();
		SudokuMakerGUI gui = new SudokuMakerGUI();
		gui.displaySudoku(sudokuN, new Sudoku(difficulty),SudokuMakerGUI.FOURDISPLAY);
		sudokus.add(sudokuN, puzzleNumber % 2, puzzleNumber / 2);
	}
	
	/**
	 * 	scales the node to width of printed A4 page with minimum borders
	 * 
	 * @param nodeToPrint JavaFX node to print
	 * @param page page to close once operation is complete 
	 */
	private static void print(Node nodeToPrint,Stage page)
	{
		PrinterJob job = PrinterJob.createPrinterJob();
		PageLayout pageLayout = Printer.getDefaultPrinter().createPageLayout(Paper.A4, PageOrientation.PORTRAIT, Printer.MarginType.HARDWARE_MINIMUM);
		
		double scaleX = pageLayout.getPrintableWidth() / nodeToPrint.getBoundsInParent().getWidth();
        double scaleY = pageLayout.getPrintableHeight() / nodeToPrint.getBoundsInParent().getHeight();
        
        Scale scale;
        // keep square so scale based on smallest number
        if(scaleX > scaleY)
        {
        	scale = new Scale(scaleY, scaleY);
        }
        else
        {
        	scale = new Scale(scaleX, scaleX);
        }
		if (job != null) {
		
		if(job.showPrintDialog(page))
		{
			nodeToPrint.getTransforms().add(scale);
			page.hide();
			boolean success = job.printPage(pageLayout,nodeToPrint);
	
			if (success) 
			{		
				job.endJob();
			}
			else
			{
				System.out.println("job failed");
			}
		}
	
		}
	}
}
